import subprocess
import paramiko
import pyipmi.interfaces
import pyipmi.chassis
from pysnmp.hlapi import *
import threading
import time

class MonitoringThread(threading.Thread):
    """后台监控线程"""
    def __init__(self):
        super().__init__()
        self._stop_event = threading.Event()
        self.daemon = True  # 设置为守护线程

    def stop(self):
        self._stop_event.set()

    def run(self):
        while not self._stop_event.is_set():
            try:
                self.update_all_hosts()
            except Exception as e:
                print(f"监控更新错误: {str(e)}")
            time.sleep(300)  # 每5分钟更新一次

    def update_all_hosts(self):
        from .models import Host
        hosts = Host.objects.filter(status='enabled')
        for host in hosts:
            try:
                metrics = self.get_host_metrics(host)
                host.cpu_usage = metrics['cpu']
                host.memory_usage = metrics['memory']
                host.disk_usage = metrics['disk']
                host.last_check = timezone.now()
                host.save()
            except Exception as e:
                host.status = 'error'
                host.save()
                print(f"更新主机 {host.hostname} 失败: {str(e)}")

    def get_host_metrics(self, host):
        if host.monitor_type == 'ssh':
            return self.get_ssh_metrics(host)
        elif host.monitor_type == 'snmp':
            return self.get_snmp_metrics(host)
        elif host.monitor_type == 'ipmi':
            return self.get_ipmi_metrics(host)
        raise ValueError(f"不支持的监控类型: {host.monitor_type}")

    def get_ssh_metrics(self, host):
        """通过SSH获取监控数据"""
        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        try:
            ssh.connect(
                host.ip_address,
                username=host.credentials.get('username'),
                password=host.credentials.get('password'),
                timeout=10
            )

            # CPU使用率
            _, stdout, _ = ssh.exec_command("top -bn1 | grep 'Cpu(s)' | awk '{print $2}'")
            cpu_usage = float(stdout.read().decode().strip())

            # 内存使用率
            _, stdout, _ = ssh.exec_command("free | grep Mem | awk '{print $3/$2 * 100.0}'")
            memory_usage = float(stdout.read().decode().strip())

            # 磁盘使用率
            _, stdout, _ = ssh.exec_command("df / | tail -1 | awk '{print $5}' | sed 's/%//'")
            disk_usage = float(stdout.read().decode().strip())

            return {
                'cpu': cpu_usage,
                'memory': memory_usage,
                'disk': disk_usage
            }
        finally:
            ssh.close()

    def get_snmp_metrics(self, host):
        """通过SNMP获取监控数据"""
        community = host.credentials.get('community', 'public')
        
        def get_snmp_value(oid):
            errorIndication, errorStatus, errorIndex, varBinds = next(
                getCmd(SnmpEngine(),
                    CommunityData(community, mpModel=0),
                    UdpTransportTarget((host.ip_address, 161)),
                    ContextData(),
                    ObjectType(ObjectIdentity(oid)))
            )
            if errorIndication:
                raise Exception(f'SNMP错误: {errorIndication}')
            return varBinds[0][1]

        # 这里使用示例OID，需要根据实际设备调整
        cpu_oid = '1.3.6.1.4.1.2021.11.9.0'  # CPU负载
        mem_oid = '1.3.6.1.4.1.2021.4.11.0'  # 内存使用
        disk_oid = '1.3.6.1.4.1.2021.9.1.9.1'  # 磁盘使用

        return {
            'cpu': float(get_snmp_value(cpu_oid)),
            'memory': float(get_snmp_value(mem_oid)),
            'disk': float(get_snmp_value(disk_oid))
        }

    def get_ipmi_metrics(self, host):
        """通过IPMI获取监控数据"""
        interface = pyipmi.interfaces.create_interface('rmcp',
                                                     slave_address=0x81,
                                                     host_target_address=0x20)
        ipmi = pyipmi.create_connection(interface)
        ipmi.session.set_session_type_rmcp(host.ip_address)
        ipmi.session.set_auth_type_user(host.credentials.get('username'),
                                      host.credentials.get('password'))
        ipmi.target = pyipmi.Target(ipmb_address=0x20)
        ipmi.session.establish()

        try:
            # 获取传感器读数
            readings = ipmi.chassis.get_system_boot_options()
            # 这里需要根据实际IPMI设备的传感器来获取CPU、内存、磁盘等信息
            return {
                'cpu': 50.0,  # 示例值
                'memory': 60.0,
                'disk': 70.0
            }
        finally:
            ipmi.session.close() 